home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Utilities / vim-5.1 / src / tag.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-05  |  56.6 KB  |  2,349 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /*
  10.  * Code to handle tags and the tag stack
  11.  */
  12.  
  13. #if defined MSDOS || defined WIN32
  14. # include <io.h>    /* for lseek(), must be before vim.h */
  15. #endif
  16.  
  17. #include "vim.h"
  18.  
  19. #ifdef HAVE_FCNTL_H
  20. # include <fcntl.h>    /* for lseek() */
  21. #endif
  22.  
  23. struct tag_pointers
  24. {
  25.     /* filled in by parse_tag_line(): */
  26.     char_u    *tagname;    /* start of tag name (skip "file:") */
  27.     char_u    *tagname_end;    /* char after tag name */
  28.     char_u    *fname;        /* first char of file name */
  29.     char_u    *fname_end;    /* char after file name */
  30.     char_u    *command;    /* first char of command */
  31.     /* filled in by parse_match(): */
  32.     char_u    *command_end;    /* first char of command */
  33.     char_u    *tag_fname;    /* file name of the tags file */
  34. #ifdef EMACS_TAGS
  35.     int        is_etag;    /* TRUE for emacs tag */
  36. #endif
  37.     char_u    *tagkind;    /* "kind:" value */
  38.     char_u    *tagkind_end;    /* end of tagkind */
  39. };
  40.  
  41. /*
  42.  * The matching tags are first stored in ga_match[].  In which one depends on
  43.  * the priority of the match.
  44.  * At the end, the matches from ga_match[] are concatenated, to make a list
  45.  * sorted on priority.
  46.  */
  47. #define MT_ST_CUR    0        /* static match in current file */
  48. #define MT_GL_CUR    1        /* global match in current file */
  49. #define MT_GL_OTH    2        /* global match in other file */
  50. #define MT_ST_OTH    3        /* static match in other file */
  51. #define MT_IC_ST_CUR    4        /* icase static match in current file */
  52. #define MT_IC_GL_CUR    5        /* icase global match in current file */
  53. #define MT_IC_GL_OTH    6        /* icase global match in other file */
  54. #define MT_IC_ST_OTH    7        /* icase static match in other file */
  55. #define MT_IC_OFF    4        /* add for icase match */
  56. #define MT_RE_OFF    8        /* add for regexp match */
  57. #define MT_MASK        7        /* mask for printing priority */
  58. #define MT_COUNT    16
  59.  
  60. static char    *mt_names[MT_COUNT/2] =
  61.         {"FSC", "F C", "F  ", "FS ", " SC", "  C", "   ", " S "};
  62.  
  63. #define NOTAGFILE    99        /* return value for jumpto_tag */
  64. static char_u    *nofile_fname = NULL;    /* fname for NOTAGFILE error */
  65.  
  66. static void taglen_advance __ARGS((int l));
  67. static int get_tagfname __ARGS((int first, char_u *buf));
  68.  
  69. static int jumpto_tag __ARGS((char_u *lbuf, int forceit));
  70. #ifdef EMACS_TAGS
  71. static int parse_tag_line __ARGS((char_u *lbuf, int is_etag, struct tag_pointers *tagp));
  72. #else
  73. static int parse_tag_line __ARGS((char_u *lbuf, struct tag_pointers *tagp));
  74. #endif
  75. static int test_for_static __ARGS((struct tag_pointers *));
  76. static int parse_match __ARGS((char_u *lbuf, struct tag_pointers *tagp));
  77. static char_u *expand_rel_name __ARGS((char_u *fname, char_u *tag_fname));
  78. #ifdef EMACS_TAGS
  79. static int test_for_current __ARGS((int, char_u *, char_u *, char_u *));
  80. #else
  81. static int test_for_current __ARGS((char_u *, char_u *, char_u *));
  82. #endif
  83. static int find_extra __ARGS((char_u **pp));
  84.  
  85. static char_u *bottommsg = (char_u *)"at bottom of tag stack";
  86. static char_u *topmsg = (char_u *)"at top of tag stack";
  87.  
  88. /*
  89.  * Jump to tag; handling of tag commands and tag stack
  90.  *
  91.  * *tag != NUL: ":tag {tag}", jump to new tag, add to tag stack
  92.  *
  93.  * type == DT_TAG:    ":tag [tag]", jump to newer position or same tag again
  94.  * type == DT_HELP:    like DT_TAG, but don't use regexp.
  95.  * type == DT_POP:    ":pop" or CTRL-T, jump to old position
  96.  * type == DT_NEXT:    jump to next match of same tag
  97.  * type == DT_PREV:    jump to previous match of same tag
  98.  * type == DT_FIRST:    jump to first match of same tag
  99.  * type == DT_LAST:    jump to first match of same tag
  100.  * type == DT_SELECT:    ":tselect [tag]", select tag from a list of all matches
  101.  * type == DT_JUMP:    ":tjump [tag]", jump to tag or select tag from a list
  102.  */
  103.     void
  104. do_tag(tag, type, count, forceit)
  105.     char_u    *tag;        /* tag (pattern) to jump to */
  106.     int        type;
  107.     int        count;
  108.     int        forceit;    /* :ta with ! */
  109. {
  110.     struct taggy    *tagstack = curwin->w_tagstack;
  111.     int            tagstackidx = curwin->w_tagstackidx;
  112.     int            tagstacklen = curwin->w_tagstacklen;
  113.     int            cur_match = 0;
  114.     int            oldtagstackidx = tagstackidx;
  115.     int            prev_num_matches;
  116.     int            new_tag = FALSE;
  117.     int            i;
  118.     int            ic;
  119.     char_u        *p;
  120.     char_u        *name;
  121.     int            no_regexp = FALSE;
  122.     int            error_cur_match = 0;
  123.     char_u        *command_end;
  124.     int            save_pos = FALSE;
  125.     struct filemark    saved_fmark;
  126.     int            taglen;
  127.  
  128.     /* remember the matches for the last used tag */
  129.     static int        num_matches = 0;
  130.     static int        max_num_matches = 0;  /* limit used for match search */
  131.     static char_u    **matches = NULL;
  132.     static int        flags;
  133.     static char_u    *matchname = NULL;
  134.  
  135.     if (type == DT_HELP)
  136.     {
  137.     type = DT_TAG;
  138.     no_regexp = TRUE;
  139.     }
  140.  
  141.     prev_num_matches = num_matches;
  142.     nofile_fname = NULL;
  143.  
  144.     /* new pattern, add to the tag stack */
  145.     if ((type == DT_TAG || type == DT_SELECT || type == DT_JUMP) && *tag)
  146.     {
  147.     /*
  148.      * If the last used entry is not at the top, delete all tag stack
  149.      * entries above it.
  150.      */
  151.     while (tagstackidx < tagstacklen)
  152.         vim_free(tagstack[--tagstacklen].tagname);
  153.  
  154.     /* if the tagstack is full: remove oldest entry */
  155.     if (++tagstacklen > TAGSTACKSIZE)
  156.     {
  157.         tagstacklen = TAGSTACKSIZE;
  158.         vim_free(tagstack[0].tagname);
  159.         for (i = 1; i < tagstacklen; ++i)
  160.         tagstack[i - 1] = tagstack[i];
  161.         --tagstackidx;
  162.     }
  163.  
  164.     /*
  165.      * put the tag name in the tag stack
  166.      */
  167.     if ((tagstack[tagstackidx].tagname = vim_strsave(tag)) == NULL)
  168.     {
  169.         --tagstacklen;
  170.         goto end_do_tag;
  171.     }
  172.     new_tag = TRUE;
  173.     save_pos = TRUE;    /* save the cursor position below */
  174.     }
  175.     else
  176.     {
  177.     if (tagstacklen == 0)            /* empty stack */
  178.     {
  179.         EMSG(e_tagstack);
  180.         goto end_do_tag;
  181.     }
  182.  
  183.     if (type == DT_POP)        /* go to older position */
  184.     {
  185.         if ((tagstackidx -= count) < 0)
  186.         {
  187.         emsg(bottommsg);
  188.         if (tagstackidx + count == 0)
  189.         {
  190.             /* We did [num]^T from the bottom of the stack */
  191.             tagstackidx = 0;
  192.             goto end_do_tag;
  193.         }
  194.         /* We weren't at the bottom of the stack, so jump all the
  195.          * way to the bottom now.
  196.          */
  197.         tagstackidx = 0;
  198.         }
  199.         else if (tagstackidx >= tagstacklen)    /* count == 0? */
  200.         {
  201.         emsg(topmsg);
  202.         goto end_do_tag;
  203.         }
  204.         if (tagstack[tagstackidx].fmark.fnum != curbuf->b_fnum)
  205.         {
  206.         /*
  207.          * Jump to other file. If this fails (e.g. because the
  208.          * file was changed) keep original position in tag stack.
  209.          */
  210.         if (buflist_getfile(tagstack[tagstackidx].fmark.fnum,
  211.             tagstack[tagstackidx].fmark.mark.lnum,
  212.             GETF_SETMARK, forceit) == FAIL)
  213.         {
  214.             tagstackidx = oldtagstackidx;  /* back to old posn */
  215.             goto end_do_tag;
  216.         }
  217.         }
  218.         else
  219.         curwin->w_cursor.lnum = tagstack[tagstackidx].fmark.mark.lnum;
  220.         curwin->w_cursor.col = tagstack[tagstackidx].fmark.mark.col;
  221.         curwin->w_set_curswant = TRUE;
  222.         /* remove the old list of matches */
  223.         FreeWild(num_matches, matches);
  224.         num_matches = 0;
  225.         goto end_do_tag;
  226.     }
  227.  
  228.     if (type == DT_TAG)        /* go to newer pattern */
  229.     {
  230.         save_pos = TRUE;        /* save the cursor position below */
  231.         if ((tagstackidx += count - 1) >= tagstacklen)
  232.         {
  233.         /*
  234.          * Beyond the last one, just give an error message and go to
  235.          * the last one.  Don't store the cursor postition.
  236.          */
  237.         tagstackidx = tagstacklen - 1;
  238.         emsg(topmsg);
  239.         save_pos = FALSE;
  240.         }
  241.         else if (tagstackidx < 0)        /* must have been count == 0 */
  242.         {
  243.         emsg(bottommsg);
  244.         tagstackidx = 0;
  245.         goto end_do_tag;
  246.         }
  247.         cur_match = tagstack[tagstackidx].cur_match;
  248.         new_tag = TRUE;
  249.     }
  250.     else                /* go to other matching tag */
  251.     {
  252.         if (--tagstackidx < 0)
  253.         tagstackidx = 0;
  254.         cur_match = tagstack[tagstackidx].cur_match;
  255.         switch (type)
  256.         {
  257.         case DT_FIRST: cur_match = count - 1; break;
  258.         case DT_SELECT:
  259.         case DT_JUMP:
  260.         case DT_LAST:  cur_match = MAXCOL - 1; break;
  261.         case DT_NEXT:  cur_match += count; break;
  262.         case DT_PREV:  cur_match -= count; break;
  263.         }
  264.         if (cur_match >= MAXCOL)
  265.         cur_match = MAXCOL - 1;
  266.         else if (cur_match < 0)
  267.         cur_match = 0;
  268.     }
  269.     }
  270.  
  271.     /*
  272.      * For ":tag [arg]" or ":tselect" remember position before the jump.
  273.      */
  274.     saved_fmark = tagstack[tagstackidx].fmark;
  275.     if (save_pos)
  276.     {
  277.     tagstack[tagstackidx].fmark.mark = curwin->w_cursor;
  278.     tagstack[tagstackidx].fmark.fnum = curbuf->b_fnum;
  279.     }
  280.  
  281.     /* curwin will change in the call to jumpto_tag() if ":stag" was used */
  282.     curwin->w_tagstackidx = tagstackidx;
  283.     curwin->w_tagstacklen = tagstacklen;
  284.     if (type != DT_SELECT && type != DT_JUMP)
  285.     curwin->w_tagstack[tagstackidx].cur_match = cur_match;
  286.  
  287.     /*
  288.      * Repeat searching for tags, when a file has not been found.
  289.      */
  290.     for (;;)
  291.     {
  292.     /*
  293.      * When desired match not found yet, try to find it (and others).
  294.      */
  295.     name = tagstack[tagstackidx].tagname;
  296.     if (new_tag
  297.         || (cur_match >= num_matches && max_num_matches != MAXCOL)
  298.         || matchname == NULL
  299.         || STRCMP(matchname, name) != 0)
  300.     {
  301.         FreeWild(num_matches, matches);
  302.         num_matches = 0;
  303.         matches = NULL;
  304.         vim_free(matchname);
  305.         matchname = vim_strsave(name);
  306.  
  307.         if (type == DT_SELECT || type == DT_JUMP)
  308.         cur_match = MAXCOL - 1;
  309.         max_num_matches = cur_match + 1;
  310.  
  311.         /* when argument starts with '/', use it as a regexp */
  312.         if (!no_regexp && *name == '/')
  313.         {
  314.         flags = TAG_REGEXP;
  315.         ++name;
  316.         }
  317.         else
  318.         flags = TAG_NOIC;
  319.  
  320.         if (find_tags(name, &num_matches, &matches,
  321.                          flags, max_num_matches) == OK
  322.             && num_matches < max_num_matches)
  323.         /* If less than max_num_matches found: all matches found. */
  324.         max_num_matches = MAXCOL;
  325.     }
  326.  
  327.     /*
  328.      * Jump to the desired match.
  329.      */
  330.     if (num_matches <= 0)
  331.         EMSG("tag not found");
  332.     else
  333.     {
  334.         if (type == DT_SELECT || (type == DT_JUMP && num_matches > 1))
  335.         {
  336.         struct tag_pointers tagp;
  337.  
  338.         /*
  339.          * List all the matching tags.
  340.          * Assume that the first match indicates how long the tags can
  341.          * be, and align the file names to that.
  342.          */
  343.         parse_match(matches[0], &tagp);
  344.         taglen = tagp.tagname_end - tagp.tagname + 2;
  345.         if (taglen < 18)
  346.             taglen = 18;
  347.         if (taglen > Columns - 25)
  348.             taglen = MAXCOL;
  349.         MSG_PUTS_ATTR("  # pri kind tag", highlight_attr[HLF_T]);
  350.         msg_clr_eos();
  351.         taglen_advance(taglen);
  352.         MSG_PUTS_ATTR("file\n", highlight_attr[HLF_T]);
  353.  
  354.         for (i = 0; i < num_matches; ++i)
  355.         {
  356.             parse_match(matches[i], &tagp);
  357.             if (!new_tag && i == tagstack[tagstackidx].cur_match)
  358.             *IObuff = '>';
  359.             else
  360.             *IObuff = ' ';
  361.             sprintf((char *)IObuff + 1, "%2d %s ", i + 1,
  362.                        mt_names[matches[i][0] & MT_MASK]);
  363.             msg_puts(IObuff);
  364.             if (tagp.tagkind != NULL)
  365.             msg_outtrans_len(tagp.tagkind,
  366.                       (int)(tagp.tagkind_end - tagp.tagkind));
  367.             msg_advance(13);
  368.             msg_outtrans_len_attr(tagp.tagname,
  369.                        (int)(tagp.tagname_end - tagp.tagname),
  370.                                highlight_attr[HLF_D]);
  371.             msg_putchar(' ');
  372.             taglen_advance(taglen);
  373.             msg_outtrans_len_attr(tagp.fname,
  374.                       (int)(tagp.fname_end - tagp.fname),
  375.                                highlight_attr[HLF_D]);
  376.             msg_putchar('\n');
  377.             msg_advance(15);
  378.  
  379.             /* print any extra fields */
  380.             command_end = tagp.command_end;
  381.             if (command_end != NULL)
  382.             {
  383.             p = command_end + 3;
  384.             while (*p)
  385.             {
  386.                 /* skip "file:" without a value (static tag) */
  387.                 if (STRNCMP(p, "file:", 5) == 0
  388.                              && vim_isspace(p[5]))
  389.                 {
  390.                 p += 6;
  391.                 continue;
  392.                 }
  393.                 /* skip "kind:<kind>" and "<kind>" */
  394.                 if (p == tagp.tagkind
  395.                     || (p + 5 == tagp.tagkind
  396.                         && STRNCMP(p, "kind:", 5) == 0))
  397.                 {
  398.                 p = tagp.tagkind_end;
  399.                 if (*p == TAB)
  400.                     ++p;
  401.                 continue;
  402.                 }
  403.  
  404.                 if (*p == '\r' || *p == '\n')
  405.                 break;
  406.  
  407.                 while (*p && *p != '\r' && *p != '\n' && *p != TAB)
  408.                 {
  409.                 if (msg_col + charsize(*p) >= Columns)
  410.                 {
  411.                     msg_putchar('\n');
  412.                     msg_advance(15);
  413.                 }
  414.                 msg_puts_attr(transchar(*p),
  415.                               highlight_attr[HLF_CM]);
  416.                 ++p;
  417.                 }
  418.             }
  419.             if (msg_col > 15)
  420.             {
  421.                 msg_putchar('\n');
  422.                 msg_advance(15);
  423.             }
  424.             }
  425.             else
  426.             {
  427.             for (p = tagp.command;
  428.                       *p && *p != '\r' && *p != '\n'; ++p)
  429.                 ;
  430.             command_end = p;
  431.             }
  432.  
  433.             /*
  434.              * Put the info (in several lines) at column 15.
  435.              * Don't display "/^" and "?^".
  436.              */
  437.             p = tagp.command;
  438.             if (*p == '/' || *p == '?')
  439.             {
  440.             ++p;
  441.             if (*p == '^')
  442.                 ++p;
  443.             }
  444.             while (p != command_end)
  445.             {
  446.             if (msg_col + (*p == TAB ? 1 : charsize(*p)) > Columns)
  447.                 msg_putchar('\n');
  448.             msg_advance(15);
  449.  
  450.             /* skip backslash used for escaping command char */
  451.             if (*p == '\\' && *(p + 1) == *tagp.command)
  452.                 ++p;
  453.  
  454.             if (*p == TAB)
  455.                 msg_putchar(' ');
  456.             else
  457.                 msg_puts(transchar(*p));
  458.             ++p;
  459.  
  460.             /* don't display the "$/;\"" and "$?;\"" */
  461.             if (p == command_end - 2 && *p == '$'
  462.                          && *(p + 1) == *tagp.command)
  463.                 break;
  464.             if (p == command_end - 1 && *p == *tagp.command)
  465.                 break;
  466.             }
  467.             if (msg_col)
  468.             msg_putchar('\n');
  469.             ui_breakcheck();
  470.             if (got_int)
  471.             {
  472.             got_int = FALSE;    /* only stop the listing */
  473.             break;
  474.             }
  475.         }
  476.  
  477.         /*
  478.          * Ask to select a tag from the list.
  479.          */
  480.         MSG_PUTS("Enter nr of choice (<CR> to abort): ");
  481.         i = get_number(TRUE);
  482.         if (KeyTyped)        /* don't call wait_return() now */
  483.         {
  484.             msg_putchar('\n');
  485.             dont_wait_return = TRUE;
  486.             need_wait_return = FALSE;
  487.             msg_didany = FALSE;
  488.             cmdline_row = msg_row;
  489.             msg_scrolled = 0;
  490.             redraw_all_later(NOT_VALID);
  491.         }
  492.         if (i <= 0 || i > num_matches || got_int)
  493.         {
  494.             /* no valid choice: don't change anything */
  495.             tagstack[tagstackidx].fmark = saved_fmark;
  496.             ++tagstackidx;
  497.             break;
  498.         }
  499.         cur_match = i - 1;
  500.         }
  501.  
  502.         if (cur_match >= num_matches)
  503.         cur_match = num_matches - 1;
  504.         curwin->w_tagstack[tagstackidx].cur_match = cur_match;
  505.         ++tagstackidx;
  506.  
  507.         /*
  508.          * Only when going to try the next match, report that the previous
  509.          * file didn't exist.  Otherwise an EMSG() is given below.
  510.          */
  511.         if (nofile_fname != NULL && error_cur_match != cur_match)
  512.         smsg((char_u *)"File \"%s\" does not exist", nofile_fname);
  513.  
  514.  
  515.         ic = (matches[cur_match][0] & MT_IC_OFF);
  516.         if (type != DT_SELECT && type != DT_JUMP && (num_matches > 1 || ic))
  517.         {
  518.         /* Give an indication of the number of matching tags */
  519.         sprintf((char *)msg_buf, "tag %d of %c%d",
  520.                 cur_match + 1,
  521.                 max_num_matches != MAXCOL ? '>' : ' ',
  522.                 num_matches);
  523.         if (ic)
  524.             STRCAT(msg_buf, "  Using tag with different case!");
  525.         if ((num_matches > prev_num_matches || new_tag)
  526.                                && num_matches > 1)
  527.         {
  528.             if (ic)
  529.             msg_attr(msg_buf, highlight_attr[HLF_W]);
  530.             else
  531.             msg(msg_buf);
  532.             msg_scroll = TRUE;    /* don't overwrite this message */
  533.         }
  534.         else
  535.             give_warning(msg_buf, ic);
  536.         if (ic && !msg_scrolled)
  537.         {
  538.             out_flush();
  539.             ui_delay(1000L, TRUE);
  540.         }
  541.         }
  542.  
  543.         if (jumpto_tag(matches[cur_match], forceit) == NOTAGFILE)
  544.         {
  545.         /* File not found: try again with another matching tag */
  546.         if ((type == DT_PREV && cur_match > 0)
  547.             || ((type == DT_TAG || type == DT_NEXT
  548.                               || type == DT_FIRST)
  549.                 && (max_num_matches != MAXCOL
  550.                          || cur_match < num_matches - 1)))
  551.         {
  552.             error_cur_match = cur_match;
  553.             --tagstackidx;
  554.             if (type == DT_PREV)
  555.             --cur_match;
  556.             else
  557.             {
  558.             type = DT_NEXT;
  559.             ++cur_match;
  560.             }
  561.             continue;
  562.         }
  563.         EMSG2("File \"%s\" does not exist", nofile_fname);
  564.         }
  565.     }
  566.     break;
  567.     }
  568.  
  569. end_do_tag:
  570.     curwin->w_tagstackidx = tagstackidx;
  571.     curwin->w_tagstacklen = tagstacklen;
  572. }
  573.  
  574.     static void
  575. taglen_advance(l)
  576.     int        l;
  577. {
  578.     if (l == MAXCOL)
  579.     {
  580.     msg_putchar('\n');
  581.     msg_advance(24);
  582.     }
  583.     else
  584.     msg_advance(13 + l);
  585. }
  586.  
  587. /*
  588.  * Print the tag stack
  589.  */
  590.     void
  591. do_tags()
  592. {
  593.     int            i;
  594.     char_u        *name;
  595.     struct taggy    *tagstack = curwin->w_tagstack;
  596.     int            tagstackidx = curwin->w_tagstackidx;
  597.     int            tagstacklen = curwin->w_tagstacklen;
  598.  
  599.     /* Highlight title */
  600.     MSG_PUTS_TITLE("\n  # TO tag         FROM line  in file");
  601.     for (i = 0; i < tagstacklen; ++i)
  602.     {
  603.     if (tagstack[i].tagname != NULL)
  604.     {
  605.         name = fm_getname(&(tagstack[i].fmark));
  606.         if (name == NULL)        /* file name not available */
  607.         continue;
  608.  
  609.         msg_putchar('\n');
  610.         sprintf((char *)IObuff, "%c%2d %2d %-15s %5ld  %s",
  611.         i == tagstackidx ? '>' : ' ',
  612.         i + 1,
  613.         tagstack[i].cur_match + 1,
  614.         tagstack[i].tagname,
  615.         tagstack[i].fmark.mark.lnum,
  616.         name);
  617.         msg_outtrans(IObuff);
  618.         vim_free(name);
  619.     }
  620.     out_flush();            /* show one line at a time */
  621.     }
  622.     if (tagstackidx == tagstacklen)    /* idx at top of stack */
  623.     MSG_PUTS("\n>");
  624. }
  625.  
  626. /*
  627.  * find_tags() - search for tags in tags files
  628.  *
  629.  * Return FAIL if search completely failed (*num_matches will be 0, *matchesp
  630.  * will be NULL), OK otherwise.
  631.  *
  632.  * There is a priority in which type of tag is recognized.
  633.  *
  634.  *  6.    A static or global tag with a full matching tag for the current file.
  635.  *  5.    A global tag with a full matching tag for another file.
  636.  *  4.    A static tag with a full matching tag for another file.
  637.  *  3.    A static or global tag with an ignore-case matching tag for the
  638.  *    current file.
  639.  *  2.    A global tag with an ignore-case matching tag for another file.
  640.  *  1.    A static tag with an ignore-case matching tag for another file.
  641.  *
  642.  * Tags in an emacs-style tags file are always global.
  643.  *
  644.  * flags:
  645.  * TAG_HELP    only search for help tags
  646.  * TAG_NAMES    only return name of tag
  647.  * TAG_REGEXP    use "pat" as a regexp
  648.  * TAG_NOIC    don't always ignore case
  649.  */
  650.  
  651.     int
  652. find_tags(pat, num_matches, matchesp, flags, mincount)
  653.     char_u    *pat;            /* pattern to search for */
  654.     int        *num_matches;        /* return: number of matches found */
  655.     char_u    ***matchesp;        /* return: array of matches found */
  656.     int        flags;
  657.     int        mincount;        /*  MAXCOL: find all matches
  658.                          other: minimal number of matches */
  659. {
  660.     FILE       *fp;
  661.     char_u     *lbuf;            /* line buffer */
  662.     char_u     *tag_fname;        /* name of tag file */
  663.     int        first_file;        /* trying first tag file */
  664.     struct tag_pointers tagp;
  665.     int        did_open = FALSE;    /* did open a tag file */
  666.     int        stop_searching = FALSE;    /* stop when match found or error */
  667.     int        retval = FAIL;        /* return value */
  668.     int        is_static;        /* current tag line is static */
  669.     int        is_current;        /* file name matches */
  670.     int        eof;            /* found end-of-file */
  671.     char_u    *p;
  672.     char_u    *s;
  673.     int        i;
  674.     vim_regexp    *prog = NULL;        /* regexp program or NULL */
  675. #ifdef BINARY_TAGS
  676.     struct tag_search_info
  677.     {
  678.     long    low_offset;    /* Low file offset of search range */
  679.     long    high_offset;    /* High file offset of search range */
  680.     long    curr_offset;    /* Current file offset in search range */
  681.     long    match_offset;    /* Where the binary search found a tag */
  682.     }        search_info;    /* Binary search file offsets */
  683.     off_t    filesize;
  684.     int        tagcmp;
  685.     long    offset;
  686. #endif
  687.     enum
  688.     {
  689.     TS_START,        /* at start of file */
  690.     TS_LINEAR,        /* linear searching forward, till EOF */
  691. #ifdef BINARY_TAGS
  692.     TS_BINARY,        /* binary searching */
  693.     TS_SKIP_BACK,        /* skipping backwards */
  694.     TS_STEP_FORWARD        /* stepping forwards */
  695. #endif
  696.     }    state;            /* Current search state */
  697.  
  698.     int        cmplen;
  699.     int        match;        /* matches */
  700.     int        match_no_ic = 0;/* matches with reg_ic == FALSE */
  701.     int        match_re = 0;    /* match with regexp */
  702.     int        matchoff = 0;
  703.  
  704. #ifdef EMACS_TAGS
  705.     /*
  706.      * Stack for included emacs-tags file.
  707.      * It has a fixed size, to truncate cyclic includes. jw
  708.      */
  709. # define INCSTACK_SIZE 42
  710.     struct
  711.     {
  712.     FILE    *fp;
  713.     char_u    *etag_fname;
  714.     } incstack[INCSTACK_SIZE];
  715.  
  716.     int        incstack_idx = 0;    /* index in incstack */
  717.     char_u     *ebuf;            /* aditional buffer for etag fname */
  718.     int        is_etag;        /* current file is emaces style */
  719. #endif
  720.  
  721.     struct growarray ga_match[MT_COUNT];
  722.     int        match_count = 0;        /* number of matches found */
  723.     char_u    **matches;
  724.     int        mtt;
  725.     int        len;
  726.     int        help_save;
  727.  
  728.     int        patlen;                /* length of pat[] */
  729.     char_u    *pathead;            /* start of pattern head */
  730.     int        patheadlen;            /* length of pathead[] */
  731. #ifdef BINARY_TAGS
  732.     int        findall = (mincount == MAXCOL); /* find all matching tags */
  733. #endif
  734.     int        has_re = (flags & TAG_REGEXP);    /* regexp used */
  735.     int        help_only = (flags & TAG_HELP);
  736.     int        name_only = (flags & TAG_NAMES);
  737.     int        noic = (flags & TAG_NOIC);
  738.  
  739.     help_save = curbuf->b_help;
  740.  
  741. /*
  742.  * Allocate memory for the buffers that are used
  743.  */
  744.     if (has_re)
  745.     prog = vim_regcomp(pat, p_magic);
  746.     lbuf = alloc(LSIZE);
  747.     tag_fname = alloc(LSIZE + 1);
  748. #ifdef EMACS_TAGS
  749.     ebuf = alloc(LSIZE);
  750. #endif
  751.     for (mtt = 0; mtt < MT_COUNT; ++mtt)
  752.     {
  753.     ga_init(&ga_match[mtt]);
  754.     ga_match[mtt].ga_itemsize = sizeof(char_u *);
  755.     ga_match[mtt].ga_growsize = 100;
  756.     }
  757.  
  758.     /* check for out of memory situation */
  759.     if (lbuf == NULL || tag_fname == NULL
  760. #ifdef EMACS_TAGS
  761.                      || ebuf == NULL
  762. #endif
  763.                             )
  764.     goto findtag_end;
  765.  
  766. /*
  767.  * Initialize a few variables
  768.  */
  769.     if (help_only)                /* want tags from help file */
  770.     curbuf->b_help = TRUE;            /* will be restored later */
  771.  
  772.     patlen = STRLEN(pat);
  773.     if (p_tl != 0 && patlen > p_tl)        /* adjust for 'taglength' */
  774.     patlen = p_tl;
  775.  
  776.     pathead = pat;
  777.     patheadlen = patlen;
  778.     if (has_re)
  779.     {
  780.     /* When the pattern starts with '^' or "\\<", binary searching can be
  781.      * used (much faster). */
  782.     if (pat[0] == '^')
  783.         pathead = pat + 1;
  784.     else if (pat[0] == '\\' && pat[1] == '<')
  785.         pathead = pat + 2;
  786.     if (pathead == pat)
  787.         patheadlen = 0;
  788.     else
  789.         for (patheadlen = 0; pathead[patheadlen] != NUL; ++patheadlen)
  790.         if (vim_strchr((char_u *)(p_magic ? ".[~*\\$" : "\\$"),
  791.                          pathead[patheadlen]) != NULL)
  792.             break;
  793.     if (p_tl != 0 && patheadlen > p_tl)    /* adjust for 'taglength' */
  794.         patheadlen = p_tl;
  795.     }
  796.  
  797. /*
  798.  * When finding a specified number of matches, first try with matching case,
  799.  * so binary search can be used, and try ignore-case matches in a second loop.
  800.  * When finding all matches, 'tagbsearch' is off, or there is no fixed string
  801.  * to look for, ignore case right away to avoid going though the tags files
  802.  * twice.
  803.  */
  804. #ifdef BINARY_TAGS
  805.     reg_ic = (findall || patheadlen == 0 || !p_tbs);
  806.     for (;;)
  807.     {
  808. #else
  809.     reg_ic = TRUE;
  810. #endif
  811.       /* When TAG_NOIC used, and 'ignorecase' not set, don't ignore case */
  812.       if (!p_ic && noic)
  813.       reg_ic = FALSE;
  814.  
  815.       /*
  816.        * Try tag file names from tags option one by one.
  817.        */
  818.       for (first_file = TRUE; get_tagfname(first_file, tag_fname) == OK;
  819.                                 first_file = FALSE)
  820.       {
  821.     /*
  822.      * A file that doesn't exist is silently ignored.  Only when not a
  823.      * single file is found, an error message is given (further on).
  824.      */
  825.     if ((fp = fopen((char *)tag_fname, "r")) == NULL)
  826.         continue;
  827.  
  828.     did_open = TRUE;    /* remember that we found at least one file */
  829.  
  830.     state = TS_START;   /* we're at the start of the file */
  831. #ifdef EMACS_TAGS
  832.     is_etag = 0;        /* default is: not emacs style */
  833. #endif
  834.     /*
  835.      * Read and parse the lines in the file one by one
  836.      */
  837.     while (!got_int)
  838.     {
  839.         line_breakcheck();        /* check for CTRL-C typed */
  840.  
  841. #ifdef BINARY_TAGS
  842.         /*
  843.          * For binary search: compute the next offset to use.
  844.          */
  845.         if (state == TS_BINARY)
  846.         {
  847.         offset = search_info.low_offset + ((search_info.high_offset
  848.                            - search_info.low_offset) / 2);
  849.         if (offset == search_info.curr_offset)
  850.             break;    /* End the binary search without a match. */
  851.         else
  852.             search_info.curr_offset = offset;
  853.         }
  854.  
  855.         /*
  856.          * Skipping back (after a match during binary search).
  857.          */
  858.         else if (state == TS_SKIP_BACK)
  859.         {
  860.         search_info.curr_offset -= LSIZE * 2;
  861.         if (search_info.curr_offset < 0)
  862.         {
  863.             search_info.curr_offset = 0;
  864.             rewind(fp);
  865.             state = TS_STEP_FORWARD;
  866.         }
  867.         }
  868.  
  869.         /*
  870.          * When jumping around in the file, first read a line to find the
  871.          * start of the next line.
  872.          */
  873.         if (state == TS_BINARY || state == TS_SKIP_BACK)
  874.         {
  875.         /* Adjust the search file offset to the correct position */
  876.         fseek(fp, search_info.curr_offset, SEEK_SET);
  877.         eof = vim_fgets(lbuf, LSIZE, fp);
  878.         if (!eof && search_info.curr_offset)
  879.         {
  880.             search_info.curr_offset = ftell(fp);
  881.             if (search_info.curr_offset == search_info.high_offset)
  882.             {
  883.             /* oops, gone a bit too far; try from low offset */
  884.             fseek(fp, search_info.low_offset, SEEK_SET);
  885.             if (search_info.low_offset)
  886.                 (void)vim_fgets(lbuf, LSIZE, fp);
  887.             search_info.curr_offset = ftell(fp);
  888.             }
  889.             eof = vim_fgets(lbuf, LSIZE, fp);
  890.         }
  891.         /* skip empty and blank lines */
  892.         while (!eof && vim_isblankline(lbuf))
  893.         {
  894.             search_info.curr_offset = ftell(fp);
  895.             eof = vim_fgets(lbuf, LSIZE, fp);
  896.         }
  897.         if (eof)
  898.         {
  899.             /* Hit end of file.  Skip backwards. */
  900.             state = TS_SKIP_BACK;
  901.             search_info.match_offset = ftell(fp);
  902.             continue;
  903.         }
  904.         }
  905.  
  906.         /*
  907.          * Not jumping around in the file: Read the next line.
  908.          */
  909.         else
  910. #endif
  911.         {
  912.         /* skip empty and blank lines */
  913.         do
  914.         {
  915.             eof = vim_fgets(lbuf, LSIZE, fp);
  916.         } while (!eof && vim_isblankline(lbuf));
  917.  
  918.         if (eof)
  919. #ifdef EMACS_TAGS
  920.             if (incstack_idx)    /* this was an included file */
  921.             {
  922.             --incstack_idx;
  923.             fclose(fp);    /* end of this file ... */
  924.             fp = incstack[incstack_idx].fp;
  925.             STRCPY(tag_fname, incstack[incstack_idx].etag_fname);
  926.             vim_free(incstack[incstack_idx].etag_fname);
  927.             is_etag = 1;    /* (only etags can include) */
  928.             continue;    /* ... continue with parent file */
  929.             }
  930.             else
  931. #endif
  932.             break;                /* end of file */
  933.         }
  934.  
  935. #ifdef EMACS_TAGS
  936.         /*
  937.          * Emacs tags line with CTRL-L: New file name on next line.
  938.          * The file name is followed by a ','.
  939.          */
  940.         if (*lbuf == Ctrl('L'))    /* remember etag file name in ebuf */
  941.         {
  942.         is_etag = 1;        /* in case at the start */
  943.         state = TS_LINEAR;
  944.         if (!vim_fgets(ebuf, LSIZE, fp))
  945.         {
  946.             for (p = ebuf; *p && *p != ','; p++)
  947.             ;
  948.             *p = NUL;
  949.  
  950.             /*
  951.              * atoi(p+1) is the number of bytes before the next ^L
  952.              * unless it is an include statement.
  953.              */
  954.             if (STRNCMP(p + 1, "include", 7) == 0
  955.                           && incstack_idx < INCSTACK_SIZE)
  956.             {
  957.             if ((incstack[incstack_idx].etag_fname =
  958.                           vim_strsave(tag_fname)) != NULL)
  959.             {
  960.                 incstack[incstack_idx].fp = fp;
  961.                 if ((fp = fopen((char *)ebuf, "r")) == NULL)
  962.                 {
  963.                 fp = incstack[incstack_idx].fp;
  964.                 vim_free(incstack[incstack_idx].etag_fname);
  965.                 }
  966.                 else
  967.                 {
  968.                 STRCPY(tag_fname, ebuf);
  969.                 ++incstack_idx;
  970.                 }
  971.                 is_etag = 0;    /* we can include anything */
  972.             }
  973.             }
  974.         }
  975.         continue;
  976.         }
  977. #endif
  978.  
  979.         /*
  980.          * When still at the start of the file, check for Emacs tags file
  981.          * format, and for "not sorted" flag.
  982.          */
  983.         if (state == TS_START)
  984.         {
  985. #ifdef BINARY_TAGS
  986.         /*
  987.          * When there is no tag head, or ignoring case, need to do a
  988.          * linear search.
  989.          * When no "!_TAG_" is found, default to binary search.  If
  990.          * the tag file isn't sorted, the second loop will find it.
  991.          * When "!_TAG_FILE_SORTED" found: start binary search if
  992.          * flag set.
  993.          */
  994.         if (patheadlen == 0 || reg_ic)
  995.             state = TS_LINEAR;
  996.         else if (STRNCMP(lbuf, "!_TAG_", 6) > 0)
  997.             state = TS_BINARY;
  998.         else if (STRNCMP(lbuf, "!_TAG_FILE_SORTED\t", 18) == 0)
  999.         {
  1000.             /* Check sorted flag */
  1001.             if (lbuf[18] == '1')
  1002.             state = TS_BINARY;
  1003.             else
  1004.             state = TS_LINEAR;
  1005.         }
  1006. #else
  1007.         state = TS_LINEAR;
  1008. #endif
  1009.  
  1010. #ifdef BINARY_TAGS
  1011.         /*
  1012.          * When starting a binary search, get the size of the file and
  1013.          * compute the first offset.
  1014.          */
  1015.         if (state == TS_BINARY)
  1016.         {
  1017.             /* Get the tag file size (don't use fstat(), it's not
  1018.              * portable). */
  1019.             if ((filesize = lseek(fileno(fp),
  1020.                            (off_t)0L, SEEK_END)) <= 0)
  1021.             state = TS_LINEAR;
  1022.             else
  1023.             {
  1024.             lseek(fileno(fp), (off_t)0L, SEEK_SET);
  1025.  
  1026.             /* Calculate the first read offset in the file.  Start
  1027.              * the search in the middle of the file.
  1028.              */
  1029.             search_info.low_offset = 0;
  1030.             search_info.high_offset = filesize;
  1031.             }
  1032.             continue;
  1033.         }
  1034. #endif
  1035.         }
  1036.  
  1037.         /*
  1038.          * Figure out where the different strings are in this line.
  1039.          * For "normal" tags: Do a quick check if the tag matches.
  1040.          * This speeds up tag searching a lot!
  1041.          */
  1042.         if (patheadlen
  1043. #ifdef EMACS_TAGS
  1044.                 && !is_etag
  1045. #endif
  1046.                     )
  1047.         {
  1048.         tagp.tagname = lbuf;
  1049. #ifdef TAG_ANY_WHITE
  1050.         tagp.tagname_end = skiptowhite(lbuf);
  1051.         if (*tagp.tagname_end == NUL)        /* corrupted tag line */
  1052. #else
  1053.         tagp.tagname_end = vim_strchr(lbuf, TAB);
  1054.         if (tagp.tagname_end == NULL)        /* corrupted tag line */
  1055. #endif
  1056.         {
  1057.             EMSG2(e_tagformat, tag_fname);
  1058.             stop_searching = TRUE;
  1059.             break;
  1060.         }
  1061.  
  1062. #ifdef OLD_STATIC_TAGS
  1063.         /*
  1064.          * Check for old style static tag: "file:tag file .."
  1065.          */
  1066.         tagp.fname = NULL;
  1067.         for (p = lbuf; p < tagp.tagname_end; ++p)
  1068.         {
  1069.             if (*p == ':')
  1070.             {
  1071.             if (tagp.fname == NULL)
  1072. #ifdef TAG_ANY_WHITE
  1073.                 tagp.fname = skipwhite(tagp.tagname_end);
  1074. #else
  1075.                 tagp.fname = tagp.tagname_end + 1;
  1076. #endif
  1077.             if (       fnamencmp(lbuf, tagp.fname, p - lbuf) == 0
  1078. #ifdef TAG_ANY_WHITE
  1079.                 && vim_iswhite(tagp.fname[p - lbuf])
  1080. #else
  1081.                 && tagp.fname[p - lbuf] == TAB
  1082. #endif
  1083.                     )
  1084.             {
  1085.                 /* found one */
  1086.                 tagp.tagname = p + 1;
  1087.                 break;
  1088.             }
  1089.             }
  1090.         }
  1091. #endif
  1092.  
  1093.         /*
  1094.          * Skip this line if the length of the tag is different and
  1095.          * there is no regexp, or the tag is too short.
  1096.          */
  1097.         cmplen = tagp.tagname_end - tagp.tagname;
  1098.         if (p_tl != 0 && cmplen > p_tl)        /* adjust for 'taglength' */
  1099.             cmplen = p_tl;
  1100.         if (has_re && patheadlen < cmplen)
  1101.             cmplen = patheadlen;
  1102.         else if (state == TS_LINEAR && patheadlen != cmplen)
  1103.             continue;
  1104.  
  1105. #ifdef BINARY_TAGS
  1106.         if (state == TS_BINARY)
  1107.         {
  1108.             /*
  1109.              * Compare the current tag with the searched tag.
  1110.              */
  1111.             tagcmp = STRNCMP(tagp.tagname, pathead, cmplen);
  1112.  
  1113.             /*
  1114.              * A match with a shorter tag means to search forward.
  1115.              * A match with a longer tag means to search backward.
  1116.              */
  1117.             if (tagcmp == 0)
  1118.             {
  1119.             if (cmplen < patheadlen)
  1120.                 tagcmp = -1;
  1121.             else if (cmplen > patheadlen)
  1122.                 tagcmp = 1;
  1123.             }
  1124.  
  1125.             if (tagcmp == 0)
  1126.             {
  1127.             /* We've located the tag, now skip back and search
  1128.              * forward until the first matching tag is found.
  1129.              */
  1130.             state = TS_SKIP_BACK;
  1131.             search_info.match_offset = search_info.curr_offset;
  1132.             continue;
  1133.             }
  1134.             if (tagcmp < 0
  1135.              && search_info.curr_offset != search_info.low_offset)
  1136.             {
  1137.             search_info.low_offset = search_info.curr_offset;
  1138.             continue;
  1139.             }
  1140.             if (tagcmp > 0
  1141.             && search_info.curr_offset != search_info.high_offset)
  1142.             {
  1143.             search_info.high_offset = search_info.curr_offset;
  1144.             continue;
  1145.             }
  1146.  
  1147.             /* No match yet and are at the end of the binary search. */
  1148.             break;
  1149.         }
  1150.         else if (state == TS_SKIP_BACK)
  1151.         {
  1152.             if (STRNICMP(tagp.tagname, pathead, cmplen) != 0)
  1153.             state = TS_STEP_FORWARD;
  1154.             continue;
  1155.         }
  1156.         else if (state == TS_STEP_FORWARD)
  1157.         {
  1158.             if (STRNICMP(tagp.tagname, pathead, cmplen))
  1159.             {
  1160.             if (ftell(fp) > search_info.match_offset)
  1161.                 break;    /* past last match */
  1162.             else
  1163.                 continue;    /* before first match */
  1164.             }
  1165.         }
  1166.         else
  1167. #endif
  1168.             /* skip this match if it can't match */
  1169.             if (STRNICMP(tagp.tagname, pathead, cmplen))
  1170.             continue;
  1171.  
  1172.         /*
  1173.          * Can be a matching tag, isolate the file name and command.
  1174.          */
  1175. #ifdef OLD_STATIC_TAGS
  1176.         if (tagp.fname == NULL)
  1177. #endif
  1178. #ifdef TAG_ANY_WHITE
  1179.             tagp.fname = skipwhite(tagp.tagname_end);
  1180. #else
  1181.             tagp.fname = tagp.tagname_end + 1;
  1182. #endif
  1183. #ifdef TAG_ANY_WHITE
  1184.         tagp.fname_end = skiptowhite(tagp.fname);
  1185.         tagp.command = skipwhite(tagp.fname_end);
  1186.         if (*tagp.command == NUL)
  1187. #else
  1188.         tagp.fname_end = vim_strchr(tagp.fname, TAB);
  1189.         tagp.command = tagp.fname_end + 1;
  1190.         if (tagp.fname_end == NULL)
  1191. #endif
  1192.             i = FAIL;
  1193.         else
  1194.             i = OK;
  1195.         }
  1196.         else
  1197.         i = parse_tag_line(lbuf,
  1198. #ifdef EMACS_TAGS
  1199.                        is_etag,
  1200. #endif
  1201.                            &tagp);
  1202.         if (i == FAIL)
  1203.         {
  1204.         EMSG2(e_tagformat, tag_fname);
  1205.         stop_searching = TRUE;
  1206.         break;
  1207.         }
  1208.  
  1209. #ifdef EMACS_TAGS
  1210.         if (is_etag)
  1211.         tagp.fname = ebuf;
  1212. #endif
  1213.         /*
  1214.          * First try matching with the pattern literally (also when it is
  1215.          * a regexp).
  1216.          */
  1217.         cmplen = tagp.tagname_end - tagp.tagname;
  1218.         if (p_tl != 0 && cmplen > p_tl)        /* adjust for 'taglength' */
  1219.         cmplen = p_tl;
  1220.         /* if tag length does not match, don't try comparing */
  1221.         if (patlen != cmplen)
  1222.         match = FALSE;
  1223.         else
  1224.         {
  1225.         if (reg_ic)
  1226.         {
  1227.             match = (STRNICMP(tagp.tagname, pat, cmplen) == 0);
  1228.             if (match)
  1229.             match_no_ic = (STRNCMP(tagp.tagname, pat, cmplen) == 0);
  1230.         }
  1231.         else
  1232.             match = (STRNCMP(tagp.tagname, pat, cmplen) == 0);
  1233.         }
  1234.  
  1235.         /*
  1236.          * Has a regexp: Also find tags matching regexp "prog".
  1237.          */
  1238.         match_re = FALSE;
  1239.         if (!match && prog != NULL)
  1240.         {
  1241.         int    cc;
  1242.  
  1243.         cc = *tagp.tagname_end;
  1244.         *tagp.tagname_end = NUL;
  1245.         match = vim_regexec(prog, tagp.tagname, TRUE);
  1246.         matchoff = (int)(prog->startp[0] - tagp.tagname);
  1247.         if (match && reg_ic)
  1248.         {
  1249.             reg_ic = FALSE;
  1250.             match_no_ic = vim_regexec(prog, tagp.tagname, TRUE);
  1251.             reg_ic = TRUE;
  1252.         }
  1253.         *tagp.tagname_end = cc;
  1254.         match_re = TRUE;
  1255.         }
  1256.  
  1257.         /*
  1258.          * If a match is found, add it to ga_match[].
  1259.          */
  1260.         if (match)
  1261.         {
  1262.         /* Decide in which array to store this match. */
  1263.         is_current = test_for_current(
  1264. #ifdef EMACS_TAGS
  1265.             is_etag,
  1266. #endif
  1267.                  tagp.fname, tagp.fname_end, tag_fname);
  1268. #ifdef EMACS_TAGS
  1269.         is_static = FALSE;
  1270.         if (!is_etag)    /* emacs tags are never static */
  1271. #endif
  1272.         {
  1273. #ifdef OLD_STATIC_TAGS
  1274.             if (tagp.tagname != lbuf)    /* detected static tag before */
  1275.             is_static = TRUE;
  1276.             else
  1277. #endif
  1278.             is_static = test_for_static(&tagp);
  1279.         }
  1280.  
  1281.         /* decide in which of the six table to store this match */
  1282.         if (is_static)
  1283.         {
  1284.             if (is_current)
  1285.             mtt = MT_ST_CUR;
  1286.             else
  1287.             mtt = MT_ST_OTH;
  1288.         }
  1289.         else
  1290.         {
  1291.             if (is_current)
  1292.             mtt = MT_GL_CUR;
  1293.             else
  1294.             mtt = MT_GL_OTH;
  1295.         }
  1296.         if (reg_ic && !match_no_ic)
  1297.             mtt += MT_IC_OFF;
  1298.         if (match_re)
  1299.             mtt += MT_RE_OFF;
  1300.  
  1301.         if (ga_grow(&ga_match[mtt], 1) == OK)
  1302.         {
  1303.             if (help_only)
  1304.             {
  1305.             /*
  1306.              * Append the help-heuristic number after the
  1307.              * tagname, for sorting it later.
  1308.              */
  1309.             *tagp.tagname_end = NUL;
  1310.             len = tagp.tagname_end - tagp.tagname;
  1311.             p = vim_strnsave(tagp.tagname, len + 10);
  1312.             if (p != NULL)
  1313.                 sprintf((char *)p + len + 1, "%06d",
  1314.                     help_heuristic(tagp.tagname,
  1315.                     match_re ? matchoff : 0, !match_no_ic));
  1316.             *tagp.tagname_end = TAB;
  1317.             ++len;    /* compare one more char */
  1318.             }
  1319.             else if (name_only)
  1320.             {
  1321.             len = tagp.tagname_end - tagp.tagname;
  1322.             p = vim_strnsave(tagp.tagname, len);
  1323.             ++len;    /* compare one more char */
  1324.             }
  1325.             else
  1326.             {
  1327.             /* Save the tag in a buffer.
  1328.              * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf>
  1329.              * other tag: <mtt><tag_fname><NUL><NUL><lbuf>
  1330.              * without Emacs tags: <mtt><tag_fname><NUL><lbuf>
  1331.              */
  1332.             len = STRLEN(tag_fname) + STRLEN(lbuf) + 3;
  1333. #ifdef EMACS_TAGS
  1334.             if (is_etag)
  1335.                 len += STRLEN(ebuf) + 1;
  1336.             else
  1337.                 ++len;
  1338. #endif
  1339.             p = alloc(len);
  1340.             if (p != NULL)
  1341.             {
  1342.                 p[0] = mtt;
  1343.                 STRCPY(p + 1, tag_fname);
  1344.                 s = p + 1 + STRLEN(tag_fname) + 1;
  1345. #ifdef EMACS_TAGS
  1346.                 if (is_etag)
  1347.                 {
  1348.                 STRCPY(s, ebuf);
  1349.                 s += STRLEN(ebuf) + 1;
  1350.                 }
  1351.                 else
  1352.                 *s++ = NUL;
  1353. #endif
  1354.                 STRCPY(s, lbuf);
  1355.             }
  1356.             }
  1357.  
  1358.             /*
  1359.              * Don't add identical matches.
  1360.              */
  1361.             for (i = ga_match[mtt].ga_len; --i >= 0; )
  1362.             if (vim_memcmp(((char_u **)(ga_match[mtt].ga_data))[i],
  1363.                              p, (size_t)len) == 0)
  1364.                 break;
  1365.             if (i < 0)
  1366.             {
  1367.             ((char_u **)(ga_match[mtt].ga_data))
  1368.                          [ga_match[mtt].ga_len++] = p;
  1369.             ga_match[mtt].ga_room--;
  1370.             ++match_count;
  1371.             }
  1372.             else
  1373.             vim_free(p);
  1374.         }
  1375.         else    /* Out of memory! Just forget about the rest. */
  1376.         {
  1377.             retval = OK;
  1378.             stop_searching = TRUE;
  1379.             break;
  1380.         }
  1381.         }
  1382.     }
  1383.     fclose(fp);
  1384. #ifdef EMACS_TAGS
  1385.     while (incstack_idx)
  1386.     {
  1387.         --incstack_idx;
  1388.         fclose(incstack[incstack_idx].fp);
  1389.         vim_free(incstack[incstack_idx].etag_fname);
  1390.     }
  1391. #endif
  1392.     /*
  1393.      * Stop searching if sufficient tags have been found.
  1394.      */
  1395.     if (match_count >= mincount)
  1396.     {
  1397.         retval = OK;
  1398.         stop_searching = TRUE;
  1399.     }
  1400.  
  1401.     if (stop_searching)
  1402.         break;
  1403.  
  1404.       } /* end of for-each-file loop */
  1405.  
  1406. #ifdef BINARY_TAGS
  1407.       /* stop searching when already tried while ignoring case, or when
  1408.        * TAG_NOIC used, and 'ignorecase' not set */
  1409.       if (stop_searching || reg_ic || (!p_ic && noic))
  1410.       break;
  1411.       reg_ic = TRUE;    /* try another time while ignoring case */
  1412.     }
  1413. #endif
  1414.  
  1415.     if (!stop_searching)
  1416.     {
  1417.     if (!did_open)        /* never opened any tags file */
  1418.         EMSG("No tags file");
  1419.     retval = OK;        /* It's OK even when no tag found */
  1420.     }
  1421.  
  1422. findtag_end:
  1423.     vim_free(lbuf);
  1424.     vim_free(prog);
  1425.     vim_free(tag_fname);
  1426. #ifdef EMACS_TAGS
  1427.     vim_free(ebuf);
  1428. #endif
  1429.  
  1430.     /*
  1431.      * Move the matches from the ga_match[] arrays into one list of
  1432.      * matches.  When retval == FAIL, free the matches.
  1433.      */
  1434.     if (retval == FAIL)
  1435.     match_count = 0;
  1436.  
  1437.     if (match_count > 0)
  1438.     matches = (char_u **)lalloc((long_u)(match_count * sizeof(char_u *)),
  1439.                                     TRUE);
  1440.     else
  1441.     matches = NULL;
  1442.     match_count = 0;
  1443.     for (mtt = 0; mtt < MT_COUNT; ++mtt)
  1444.     {
  1445.     for (i = 0; i < ga_match[mtt].ga_len; ++i)
  1446.     {
  1447.         p = ((char_u **)(ga_match[mtt].ga_data))[i];
  1448.         if (matches == NULL)
  1449.         vim_free(p);
  1450.         else
  1451.         matches[match_count++] = p;
  1452.     }
  1453.     ga_clear(&ga_match[mtt]);
  1454.     }
  1455.  
  1456.     *matchesp = matches;
  1457.     *num_matches = match_count;
  1458.  
  1459.     curbuf->b_help = help_save;
  1460.  
  1461.     return retval;
  1462. }
  1463.  
  1464. /*
  1465.  * Get the next name of a tag file from the tag file list.
  1466.  * For help files, use "tags" file only.
  1467.  *
  1468.  * Return FAIL if no more tag file names, OK otherwise.
  1469.  */
  1470.     static int
  1471. get_tagfname(first, buf)
  1472.     int        first;        /* TRUE when first file name is wanted */
  1473.     char_u  *buf;        /* pointer to buffer of LSIZE chars */
  1474. {
  1475.     static char_u   *np = NULL;
  1476.     char_u        *fname;
  1477.     size_t        path_len, fname_len;
  1478.     /*
  1479.      * A list is kept of the files that have been visited.
  1480.      */
  1481.     struct visited
  1482.     {
  1483.     struct visited    *v_next;
  1484. #if defined(UNIX)
  1485.     struct stat    v_st;
  1486. #else
  1487.     char_u        v_fname[1];    /* actually longer */
  1488. #endif
  1489.     };
  1490.     static struct visited   *first_visited = NULL;
  1491.     struct visited        *vp;
  1492. #ifdef UNIX
  1493.     struct stat            st;
  1494. #else
  1495.     char_u            *expand_buf;
  1496. #endif
  1497.  
  1498.     if (first)
  1499.     {
  1500.     np = p_tags;
  1501.     while (first_visited != NULL)
  1502.     {
  1503.         vp = first_visited->v_next;
  1504.         vim_free(first_visited);
  1505.         first_visited = vp;
  1506.     }
  1507.     }
  1508.  
  1509.     if (np == NULL)        /* tried allready (or bogus call) */
  1510.     return FAIL;
  1511.  
  1512.     /*
  1513.      * For a help window only try the file 'tags' in the same
  1514.      * directory as 'helpfile'.
  1515.      */
  1516.     if (curbuf->b_help)
  1517.     {
  1518.     path_len = gettail(p_hf) - p_hf;
  1519.     if (path_len + 9 >= LSIZE)
  1520.         return FAIL;
  1521.     vim_memmove(buf, p_hf, path_len);
  1522.     STRCPY(buf + path_len, "tags");
  1523.  
  1524.     np = NULL;        /* try only once */
  1525.     }
  1526.  
  1527.     else
  1528.     {
  1529. #ifndef UNIX
  1530.     expand_buf = alloc(MAXPATHL);
  1531.     if (expand_buf == NULL)
  1532.         return FAIL;
  1533. #endif
  1534.  
  1535.     /*
  1536.      * Loop until we have found a file name that can be used.
  1537.      */
  1538.     for (;;)
  1539.     {
  1540.         if (*np == NUL)        /* tried all possibilities */
  1541.         {
  1542. #ifndef UNIX
  1543.         vim_free(expand_buf);
  1544. #endif
  1545.         return FAIL;
  1546.         }
  1547.  
  1548.         /*
  1549.          * Copy next file name into buf.
  1550.          */
  1551.         (void)copy_option_part(&np, buf, LSIZE, " ,");
  1552.  
  1553.         /*
  1554.          * Tag file name starting with "./": Replace '.' with path of
  1555.          * current file.
  1556.          * Only do this when 't' flag not included in 'cpo'.
  1557.          */
  1558.         if (buf[0] == '.' && vim_ispathsep(buf[1])
  1559.                      && vim_strchr(p_cpo, CPO_DOTTAG) == NULL)
  1560.         {
  1561.         if (curbuf->b_fname == NULL)    /* skip if no file name */
  1562.             continue;
  1563.  
  1564.         path_len = gettail(curbuf->b_fname) - curbuf->b_fname;
  1565.         fname = buf + 1;
  1566.         while (vim_ispathsep(*fname))    /* skip '/' and the like */
  1567.             ++fname;
  1568.         fname_len = STRLEN(fname);
  1569.         if (fname_len + path_len + 1 > LSIZE)
  1570.             continue;
  1571.         vim_memmove(buf + path_len, fname, fname_len + 1);
  1572.         vim_memmove(buf, curbuf->b_fname, path_len);
  1573.         }
  1574.  
  1575.         /*
  1576.          * Check if this tags file has been used already.
  1577.          * If file doesn't exist, skip it.
  1578.          */
  1579. #if defined(UNIX)
  1580.         if (stat((char *)buf, &st) < 0)
  1581. #else
  1582.         if (mch_FullName(buf, expand_buf, MAXPATHL, TRUE) == FAIL)
  1583. #endif
  1584.         continue;
  1585.  
  1586.         for (vp = first_visited; vp != NULL; vp = vp->v_next)
  1587. #if defined(UNIX)
  1588.         if (vp->v_st.st_dev == st.st_dev &&
  1589.                          vp->v_st.st_ino == st.st_ino)
  1590. #else
  1591.         if (fnamecmp(vp->v_fname, expand_buf) == 0)
  1592. #endif
  1593.             break;
  1594.  
  1595.         if (vp != NULL)        /* already visited, skip it */
  1596.         continue;
  1597.  
  1598.         /*
  1599.          * Found the next name.  Add it to the list of visited files.
  1600.          */
  1601. #ifdef UNIX
  1602.         vp = (struct visited *)alloc((unsigned)sizeof(struct visited));
  1603. #else
  1604.         vp = (struct visited *)alloc((unsigned)(sizeof(struct visited) +
  1605.                              STRLEN(expand_buf)));
  1606. #endif
  1607.         if (vp != NULL)
  1608.         {
  1609. #ifdef UNIX
  1610.         vp->v_st = st;
  1611. #else
  1612.         STRCPY(vp->v_fname, expand_buf);
  1613. #endif
  1614.         vp->v_next = first_visited;
  1615.         first_visited = vp;
  1616.         }
  1617.         break;
  1618.     }
  1619. #ifndef UNIX
  1620.     vim_free(expand_buf);
  1621. #endif
  1622.     }
  1623.     return OK;
  1624. }
  1625.  
  1626. /*
  1627.  * Parse one line from the tags file. Find start/end of tag name, start/end of
  1628.  * file name and start of search pattern.
  1629.  *
  1630.  * If is_etag is TRUE, tagp->fname and tagp->fname_end are not set.
  1631.  *
  1632.  * Return FAIL if there is a format error in this line, OK otherwise.
  1633.  */
  1634.     static int
  1635. parse_tag_line(lbuf,
  1636. #ifdef EMACS_TAGS
  1637.             is_etag,
  1638. #endif
  1639.                   tagp)
  1640.     char_u        *lbuf;        /* line to be parsed */
  1641. #ifdef EMACS_TAGS
  1642.     int            is_etag;
  1643. #endif
  1644.     struct tag_pointers *tagp;
  1645. {
  1646.     char_u    *p;
  1647.  
  1648. #ifdef EMACS_TAGS
  1649.     char_u    *p_7f;
  1650.  
  1651.     if (is_etag)
  1652.     {
  1653.     /*
  1654.      * There are two formats for an emacs tag line:
  1655.      * 1:  struct EnvBase ^?EnvBase^A139,4627
  1656.      * 2: #define    ARPB_WILD_WORLD ^?153,5194
  1657.      */
  1658.     p_7f = vim_strchr(lbuf, 0x7f);
  1659.     if (p_7f == NULL)
  1660.         return FAIL;
  1661.  
  1662.     /* Find ^A.  If not found the line number is after the 0x7f */
  1663.     p = vim_strchr(p_7f, Ctrl('A'));
  1664.     if (p == NULL)
  1665.         p = p_7f + 1;
  1666.     else
  1667.         ++p;
  1668.  
  1669.     if (!isdigit(*p))        /* check for start of line number */
  1670.         return FAIL;
  1671.     tagp->command = p;
  1672.  
  1673.  
  1674.     if (p[-1] == Ctrl('A'))        /* first format: explicit tagname given */
  1675.     {
  1676.         tagp->tagname = p_7f + 1;
  1677.         tagp->tagname_end = p - 1;
  1678.     }
  1679.     else                /* second format: isolate tagname */
  1680.     {
  1681.         /* find end of tagname */
  1682.         for (p = p_7f - 1; !vim_iswordc(*p); --p)
  1683.         if (p == lbuf)
  1684.             return FAIL;
  1685.         tagp->tagname_end = p + 1;
  1686.         while (p >= lbuf && vim_iswordc(*p))
  1687.         --p;
  1688.         tagp->tagname = p + 1;
  1689.     }
  1690.     }
  1691.     else    /* not an Emacs tag */
  1692.     {
  1693. #endif
  1694.     /* Isolate the tagname, from lbuf up to the first white */
  1695.     tagp->tagname = lbuf;
  1696. #ifdef TAG_ANY_WHITE
  1697.     p = skiptowhite(lbuf);
  1698. #else
  1699.     p = vim_strchr(lbuf, TAB);
  1700.     if (p == NULL)
  1701.         return FAIL;
  1702. #endif
  1703.     tagp->tagname_end = p;
  1704.  
  1705.     /* Isolate file name, from first to second white space */
  1706. #ifdef TAG_ANY_WHITE
  1707.     p = skipwhite(p);
  1708. #else
  1709.     if (*p != NUL)
  1710.         ++p;
  1711. #endif
  1712.     tagp->fname = p;
  1713. #ifdef TAG_ANY_WHITE
  1714.     p = skiptowhite(p);
  1715. #else
  1716.     p = vim_strchr(p, TAB);
  1717.     if (p == NULL)
  1718.         return FAIL;
  1719. #endif
  1720.     tagp->fname_end = p;
  1721.  
  1722.     /* find start of search command, after second white space */
  1723. #ifdef TAG_ANY_WHITE
  1724.     p = skipwhite(p);
  1725. #else
  1726.     if (*p != NUL)
  1727.         ++p;
  1728. #endif
  1729.     if (*p == NUL)
  1730.         return FAIL;
  1731.     tagp->command = p;
  1732. #ifdef EMACS_TAGS
  1733.     }
  1734. #endif
  1735.  
  1736.     return OK;
  1737. }
  1738.  
  1739. /*
  1740.  * Check if tagname is a static tag
  1741.  *
  1742.  * Static tags produced by the older ctags program have the format:
  1743.  *    'file:tag  file  /pattern'.
  1744.  * This is only recognized when both occurences of 'file' are the same, to
  1745.  * avoid recognizing "string::string" or ":exit".
  1746.  *
  1747.  * Static tags produced by the new ctags program have the format:
  1748.  *    'tag  file  /pattern/;"<Tab>file:'        "
  1749.  *
  1750.  * Return TRUE if it is a static tag and adjust *tagname to the real tag.
  1751.  * Return FALSE if it is not a static tag.
  1752.  */
  1753.     static int
  1754. test_for_static(tagp)
  1755.     struct tag_pointers    *tagp;
  1756. {
  1757.     char_u    *p;
  1758.  
  1759. #ifdef OLD_STATIC_TAGS
  1760.     int        len;
  1761.  
  1762.     /*
  1763.      * Check for old style static tag: "file:tag file .."
  1764.      */
  1765.     len = tagp->fname_end - tagp->fname;
  1766.     p = tagp->tagname + len;
  1767.     if (       p < tagp->tagname_end
  1768.         && *p == ':'
  1769.         && fnamencmp(tagp->tagname, tagp->fname, len) == 0)
  1770.     {
  1771.     tagp->tagname = p + 1;
  1772.     return TRUE;
  1773.     }
  1774. #endif
  1775.  
  1776.     /*
  1777.      * Check for new style static tag ":...<Tab>file:[<Tab>...]"
  1778.      */
  1779.     p = tagp->command;
  1780.     while ((p = vim_strchr(p, '\t')) != NULL)
  1781.     {
  1782.     ++p;
  1783.     if (STRNCMP(p, "file:", 5) == 0)
  1784.         return TRUE;
  1785.     }
  1786.  
  1787.     return FALSE;
  1788. }
  1789.  
  1790. /*
  1791.  * Parse a line from a matching tag.  Does not change the line itself.
  1792.  *
  1793.  * The line that we get looks like this:
  1794.  * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf>
  1795.  * other tag: <mtt><tag_fname><NUL><NUL><lbuf>
  1796.  * without Emacs tags: <mtt><tag_fname><NUL><lbuf>
  1797.  *
  1798.  * Return OK or FAIL.
  1799.  */
  1800.     static int
  1801. parse_match(lbuf, tagp)
  1802.     char_u        *lbuf;        /* input: matching line */
  1803.     struct tag_pointers    *tagp;        /* output: pointers into the line */
  1804. {
  1805.     int        retval;
  1806.     char_u    *p;
  1807.     char_u    *pc, *pt;
  1808.  
  1809.     tagp->tag_fname = lbuf + 1;
  1810.     lbuf += STRLEN(tagp->tag_fname) + 2;
  1811. #ifdef EMACS_TAGS
  1812.     if (*lbuf)
  1813.     {
  1814.     tagp->is_etag = TRUE;
  1815.     tagp->fname = lbuf;
  1816.     lbuf += STRLEN(lbuf);
  1817.     tagp->fname_end = lbuf++;
  1818.     }
  1819.     else
  1820.     {
  1821.     tagp->is_etag = FALSE;
  1822.     ++lbuf;
  1823.     }
  1824. #endif
  1825.  
  1826.     /* Find search pattern and the file name for non-etags. */
  1827.     retval = parse_tag_line(lbuf,
  1828. #ifdef EMACS_TAGS
  1829.             tagp->is_etag,
  1830. #endif
  1831.             tagp);
  1832.  
  1833.     tagp->tagkind = NULL;
  1834.     tagp->command_end = NULL;
  1835.  
  1836.     if (retval == OK)
  1837.     {
  1838.     /* Try to find a kind field: "kind:<kind>" or just "<kind>"*/
  1839.     p = tagp->command;
  1840.     if (find_extra(&p) == OK)
  1841.     {
  1842.         tagp->command_end = p;
  1843.         p += 3;    /* skip ";\"\t" */
  1844.         while (isalpha(*p))
  1845.         {
  1846.         if (STRNCMP(p, "kind:", 5) == 0)
  1847.         {
  1848.             tagp->tagkind = p + 5;
  1849.             break;
  1850.         }
  1851.         pc = vim_strchr(p, ':');
  1852.         pt = vim_strchr(p, '\t');
  1853.         if (pc == NULL || (pt != NULL && pc > pt))
  1854.         {
  1855.             tagp->tagkind = p;
  1856.             break;
  1857.         }
  1858.         if (pt == NULL)
  1859.             break;
  1860.         p = pt + 1;
  1861.         }
  1862.     }
  1863.     if (tagp->tagkind != NULL)
  1864.     {
  1865.         for (p = tagp->tagkind;
  1866.                 *p && *p != '\t' && *p != '\r' && *p != '\n'; ++p)
  1867.         ;
  1868.         tagp->tagkind_end = p;
  1869.     }
  1870.     }
  1871.     return retval;
  1872. }
  1873.  
  1874. /*
  1875.  * Jump to a tag that has been found in one of the tag files
  1876.  *
  1877.  * returns OK for success, NOTAGFILE when file not found, FAIL otherwise.
  1878.  */
  1879.     static int
  1880. jumpto_tag(lbuf, forceit)
  1881.     char_u    *lbuf;        /* line from the tags file for this tag */
  1882.     int        forceit;    /* :ta with ! */
  1883. {
  1884.     int        save_secure;
  1885.     int        save_magic;
  1886.     int        save_p_ws, save_p_scs, save_p_ic;
  1887.     int        csave = 0;
  1888.     char_u    *str;
  1889.     char_u    *pbuf;            /* search pattern buffer */
  1890.     char_u    *pbuf_end;
  1891.     char_u    *expanded_fname = NULL;
  1892.     char_u    *tofree_fname = NULL;
  1893.     char_u    *fname = NULL;
  1894.     struct tag_pointers tagp;
  1895.     int        retval = FAIL;
  1896.     int        getfile_result;
  1897.     int        search_options;
  1898.  
  1899.     pbuf = alloc(LSIZE);
  1900.  
  1901.     /* parse the match line into the tagp structure */
  1902.     if (pbuf == NULL || parse_match(lbuf, &tagp) == FAIL)
  1903.     {
  1904.     tagp.fname_end = NULL;
  1905.     goto erret;
  1906.     }
  1907.  
  1908.     /* truncate the file name, so it can be used as a string */
  1909.     csave = *tagp.fname_end;
  1910.     *tagp.fname_end = NUL;
  1911.     fname = tagp.fname;
  1912.  
  1913.     /* copy the command to pbuf[], remove trailing CR/NL */
  1914.     str = tagp.command;
  1915.     for (pbuf_end = pbuf; *str && *str != '\n' && *str != '\r'; )
  1916.     {
  1917. #ifdef EMACS_TAGS
  1918.     if (tagp.is_etag && *str == ',')/* stop at ',' after line number */
  1919.         break;
  1920. #endif
  1921.     *pbuf_end++ = *str++;
  1922.     }
  1923.     *pbuf_end = NUL;
  1924.  
  1925. #ifdef EMACS_TAGS
  1926.     if (!tagp.is_etag)
  1927. #endif
  1928.     {
  1929.     /*
  1930.      * Remove the "<Tab>fieldname:value" stuff; we don't need it here.
  1931.      */
  1932.     str = pbuf;
  1933.     if (find_extra(&str) == OK)
  1934.     {
  1935.         pbuf_end = str;
  1936.         *pbuf_end = NUL;
  1937.     }
  1938.     }
  1939.  
  1940.     /*
  1941.      * expand file name (for environment variables)
  1942.      */
  1943.     expanded_fname = ExpandOne((char_u *)fname, NULL, WILD_LIST_NOTFOUND,
  1944.                                 WILD_EXPAND_FREE);
  1945.     if (expanded_fname != NULL)
  1946.     fname = expanded_fname;
  1947.  
  1948.     /*
  1949.      * if 'tagrelative' option set, may change file name
  1950.      */
  1951.     fname = expand_rel_name(fname, tagp.tag_fname);
  1952.     if (fname == NULL)
  1953.     goto erret;
  1954.     tofree_fname = fname;    /* free() it later */
  1955.  
  1956.     /*
  1957.      * check if file for tag exists before abandoning current file
  1958.      */
  1959.     if (mch_getperm(fname) < 0)
  1960.     {
  1961.     retval = NOTAGFILE;
  1962.     vim_free(nofile_fname);
  1963.     nofile_fname = vim_strsave(fname);
  1964.     if (nofile_fname == NULL)
  1965.         nofile_fname = (char_u *)"";
  1966.     goto erret;
  1967.     }
  1968.  
  1969.     ++RedrawingDisabled;
  1970.  
  1971.     /* if it was a CTRL-W CTRL-] command split window now */
  1972.     if (postponed_split)
  1973.     win_split(postponed_split > 0 ? postponed_split : 0, FALSE, FALSE);
  1974.  
  1975.     /* A :ta from a help file will keep the b_help flag set. */
  1976.     keep_help_flag = curbuf->b_help;
  1977.     getfile_result = getfile(0, fname, NULL, TRUE, (linenr_t)0, forceit);
  1978.     keep_help_flag = FALSE;
  1979.  
  1980.     if (getfile_result <= 0)        /* got to the right file */
  1981.     {
  1982.     curwin->w_set_curswant = TRUE;
  1983.     postponed_split = 0;
  1984.  
  1985.     save_secure = secure;
  1986.     secure = 1;
  1987.     save_magic = p_magic;
  1988.     p_magic = FALSE;    /* always execute with 'nomagic' */
  1989.     tag_modified = FALSE;
  1990.  
  1991.     /*
  1992.      * If 'cpoptions' contains 't', store the search pattern for the "n"
  1993.      * command.  If 'cpoptions' does not contain 't', the search pattern
  1994.      * is not stored.
  1995.      */
  1996.     if (vim_strchr(p_cpo, CPO_TAGPAT) != NULL)
  1997.         search_options = 0;
  1998.     else
  1999.         search_options = SEARCH_KEEP;
  2000.  
  2001.     /*
  2002.      * If the command is a search, try here.
  2003.      *
  2004.      * Reset 'smartcase' for the search, since the search pattern was not
  2005.      * typed by the user.
  2006.      * Only use do_search() when there is a full search command, without
  2007.      * anything following.
  2008.      */
  2009.     str = pbuf;
  2010.     if (pbuf[0] == '/' || pbuf[0] == '?')
  2011.         str = skip_regexp(pbuf + 1, pbuf[0], FALSE) + 1;
  2012.     if (str > pbuf_end - 1)    /* search command with nothing following */
  2013.     {
  2014.         save_p_ws = p_ws;
  2015.         save_p_ic = p_ic;
  2016.         save_p_scs = p_scs;
  2017.         p_ws = TRUE;    /* Switch wrap-scan on temporarily */
  2018.         p_ic = FALSE;    /* don't ignore case now */
  2019.         p_scs = FALSE;
  2020.  
  2021.         /* put pattern in search history */
  2022.         add_to_history(HIST_SEARCH, pbuf + 1);
  2023.  
  2024.         curwin->w_cursor.lnum = 0;    /* start search before first line */
  2025.         if (do_search(NULL, pbuf[0], pbuf + 1, (long)1, search_options))
  2026.         retval = OK;
  2027.         else
  2028.         {
  2029.         int    found = 1;
  2030.         int    cc;
  2031.  
  2032.         /*
  2033.          * try again, ignore case now
  2034.          */
  2035.         p_ic = TRUE;
  2036.         if (!do_search(NULL, pbuf[0], pbuf + 1, (long)1,
  2037.                                   search_options))
  2038.         {
  2039.             /*
  2040.              * Failed to find pattern, take a guess: "^func  ("
  2041.              */
  2042.             found = 2;
  2043.             (void)test_for_static(&tagp);
  2044.             cc = *tagp.tagname_end;
  2045.             *tagp.tagname_end = NUL;
  2046.             sprintf((char *)pbuf, "^%s\\s\\*(", tagp.tagname);
  2047.             if (!do_search(NULL, '/', pbuf, (long)1, search_options))
  2048.             {
  2049.             /* Guess again: "^char * \<func  (" */
  2050.             sprintf((char *)pbuf, "^\\[#a-zA-Z_]\\.\\*\\<%s\\s\\*(",
  2051.                                 tagp.tagname);
  2052.             if (!do_search(NULL, '/', pbuf, (long)1,
  2053.                                   search_options))
  2054.                 found = 0;
  2055.             }
  2056.             *tagp.tagname_end = cc;
  2057.         }
  2058.         if (found == 0)
  2059.             EMSG("Can't find tag pattern");
  2060.         else
  2061.         {
  2062.             /*
  2063.              * Only give a message when really guessed, not when 'ic'
  2064.              * is set and match found while ignoring case.
  2065.              */
  2066.             if (found == 2 || !save_p_ic)
  2067.             {
  2068.             MSG("Couldn't find tag, just guessing!");
  2069.             if (!msg_scrolled)
  2070.             {
  2071.                 out_flush();
  2072.                 ui_delay(1000L, TRUE);
  2073.             }
  2074.             }
  2075.             retval = OK;
  2076.         }
  2077.         }
  2078.         p_ws = save_p_ws;
  2079.         p_ic = save_p_ic;
  2080.         p_scs = save_p_scs;
  2081.  
  2082.         /* A search command may have positioned the cursor beyond the end
  2083.          * of the line.  May need to correct that here. */
  2084.         adjust_cursor();
  2085.     }
  2086.     else
  2087.     {
  2088.         curwin->w_cursor.lnum = 1;        /* start command in line 1 */
  2089.         do_cmdline(pbuf, NULL, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
  2090.         retval = OK;
  2091.     }
  2092.  
  2093.     /*
  2094.      * When the command has set the b_changed flag, give a warning to the
  2095.      * user about this.
  2096.      */
  2097.     if (tag_modified)
  2098.     {
  2099.         secure = 2;
  2100.         EMSG("WARNING: tag command changed a buffer!!!");
  2101.     }
  2102.     if (secure == 2)        /* done something that is not allowed */
  2103.         wait_return(TRUE);
  2104.     secure = save_secure;
  2105.     p_magic = save_magic;
  2106.  
  2107.     /* Return OK if jumped to another file (at least we found the file!). */
  2108.     if (getfile_result == -1)
  2109.         retval = OK;
  2110.  
  2111.     /*
  2112.      * For a help buffer: Put the cursor line at the top of the window,
  2113.      * the help subject will be below it.
  2114.      */
  2115.     if (curbuf->b_help)
  2116.     {
  2117.         set_topline(curwin, curwin->w_cursor.lnum);
  2118.         update_topline();        /* correct for 'so' */
  2119.         update_screen(NOT_VALID);
  2120.     }
  2121.     --RedrawingDisabled;
  2122.     }
  2123.     else
  2124.     {
  2125.     --RedrawingDisabled;
  2126.     if (postponed_split)        /* close the window */
  2127.     {
  2128.         close_window(curwin, FALSE);
  2129.         postponed_split = 0;
  2130.     }
  2131.     }
  2132.  
  2133. erret:
  2134.     if (tagp.fname_end != NULL)
  2135.     *tagp.fname_end = csave;
  2136.     vim_free(pbuf);
  2137.     vim_free(tofree_fname);
  2138.     vim_free(expanded_fname);
  2139.  
  2140.     return retval;
  2141. }
  2142.  
  2143. /*
  2144.  * If 'tagrelative' option set, change fname (name of file containing tag)
  2145.  * according to tag_fname (name of tag file containing fname).
  2146.  * Returns a pointer to allocated memory (or NULL when out of memory).
  2147.  */
  2148.     static char_u *
  2149. expand_rel_name(fname, tag_fname)
  2150.     char_u    *fname;
  2151.     char_u    *tag_fname;
  2152. {
  2153.     char_u    *p;
  2154.     char_u    *retval;
  2155.  
  2156.     if ((p_tr || curbuf->b_help) && !mch_isFullName(fname) &&
  2157.                        (p = gettail(tag_fname)) != tag_fname)
  2158.     {
  2159.     retval = alloc(MAXPATHL);
  2160.     if (retval == NULL)
  2161.         return NULL;
  2162.  
  2163.     STRCPY(retval, tag_fname);
  2164.     STRNCPY(retval + (p - tag_fname), fname, MAXPATHL - (p - tag_fname));
  2165.     /*
  2166.      * Translate names like "src/a/../b/file.c" into "src/b/file.c".
  2167.      */
  2168.     simplify_filename(retval);
  2169.     }
  2170.     else
  2171.     retval = vim_strsave(fname);
  2172.  
  2173.     return retval;
  2174. }
  2175.  
  2176. /*
  2177.  * Moves the tail part of the path (including the terminating NUL) pointed to
  2178.  * by "tail" to the new location pointed to by "here". This should accomodate
  2179.  * an overlapping move.
  2180.  */
  2181. #define movetail(here, tail)  vim_memmove(here, tail, STRLEN(tail) + (size_t)1)
  2182.  
  2183. /*
  2184.  * Converts a file name into a canonical form. It simplifies a file name into
  2185.  * its simplest form by stripping out unneeded components, if any.  The
  2186.  * resulting file name is simplified in place and will either be the same
  2187.  * length as that supplied, or shorter.
  2188.  */
  2189.     void
  2190. simplify_filename(filename)
  2191.     char_u *filename;
  2192. {
  2193. #ifndef AMIGA        /* Amiga doesn't have "..", it uses "/" */
  2194.     int        components = 0;
  2195.     char_u  *p, *tail, *start;
  2196. #ifdef UNIX
  2197.     char_u  *orig = vim_strsave(filename);
  2198.  
  2199.     if (orig == NULL)
  2200.     return;
  2201. #endif
  2202.  
  2203.     p = filename;
  2204. #ifdef BACKSLASH_IN_FILENAME
  2205.     if (p[1] == ':')        /* skip "x:" */
  2206.     p += 2;
  2207. #endif
  2208.  
  2209.     while (vim_ispathsep(*p))
  2210.     ++p;
  2211.     start = p;        /* remember start after "c:/" or "/" or "//" */
  2212.  
  2213.     do
  2214.     {
  2215.     /* At this point "p" is pointing to the char following a "/". */
  2216.     if (vim_ispathsep(*p))
  2217.         movetail(p, p + 1);        /* remove duplicate "/" */
  2218.     else if (p[0] == '.' && vim_ispathsep(p[1]))
  2219.         movetail(p, p + 2);        /* strip "./" */
  2220.     else if (p[0] == '.' && p[1] == '.' && vim_ispathsep(p[2]))
  2221.     {
  2222.         if (components > 0)        /* strip one preceding component */
  2223.         {
  2224.         tail = p + 3;        /* skip to after "../" or "..///" */
  2225.         while (vim_ispathsep(*tail))
  2226.             ++tail;
  2227.         --p;
  2228.         /* skip back to after previous '/' */
  2229.         while (p > start && !vim_ispathsep(p[-1]))
  2230.             --p;
  2231.         /* skip back to after first '/' in a row */
  2232.         while (p - 1 > start && vim_ispathsep(p[-2]))
  2233.             --p;
  2234.         movetail(p, tail);    /* strip previous component */
  2235.         --components;
  2236.         }
  2237.         else            /* leading "../" */
  2238.         p += 3;            /* skip to char after "/" */
  2239.     }
  2240.     else
  2241.     {
  2242.         ++components;        /* simple path component */
  2243.         p = getnextcomp(p);
  2244.     }
  2245.     } while (p != NULL && *p != NUL);
  2246.  
  2247. #ifdef UNIX
  2248.     /* Check that the new file name is really the same file.  This will not be
  2249.      * the case when using symbolic links: "dir/link/../name" != "dir/name". */
  2250.     {
  2251.     struct stat    orig_st, new_st;
  2252.  
  2253.     if (       stat((char *)orig, &orig_st) < 0
  2254.         || stat((char *)filename, &new_st) < 0
  2255.         || orig_st.st_ino != new_st.st_ino
  2256.         || orig_st.st_dev != new_st.st_dev)
  2257.         STRCPY(filename, orig);
  2258.     vim_free(orig);
  2259.     }
  2260. #endif
  2261. #endif /* !AMIGA */
  2262. }
  2263.  
  2264. /*
  2265.  * Check if we have a tag for the current file.
  2266.  * This is a bit slow, because of the full path compare in fullpathcmp().
  2267.  * Return TRUE if tag for file "fname" if tag file "tag_fname" is for current
  2268.  * file.
  2269.  */
  2270.     static int
  2271. #ifdef EMACS_TAGS
  2272. test_for_current(is_etag, fname, fname_end, tag_fname)
  2273.     int        is_etag;
  2274. #else
  2275. test_for_current(fname, fname_end, tag_fname)
  2276. #endif
  2277.     char_u  *fname;
  2278.     char_u  *fname_end;
  2279.     char_u  *tag_fname;
  2280. {
  2281.     int        c;
  2282.     int        retval = FALSE;
  2283.     char_u  *relname;
  2284.  
  2285.     if (curbuf->b_ffname != NULL)    /* if the current buffer has a name */
  2286.     {
  2287. #ifdef EMACS_TAGS
  2288.     if (is_etag)
  2289.         c = 0;        /* to shut up GCC */
  2290.     else
  2291. #endif
  2292.     {
  2293.         c = *fname_end;
  2294.         *fname_end = NUL;
  2295.     }
  2296.     relname = expand_rel_name(fname, tag_fname);
  2297.     if (relname != NULL)
  2298.     {
  2299.         retval = (fullpathcmp(relname, curbuf->b_ffname, TRUE) & FPC_SAME);
  2300.         vim_free(relname);
  2301.     }
  2302. #ifdef EMACS_TAGS
  2303.     if (!is_etag)
  2304. #endif
  2305.         *fname_end = c;
  2306.     }
  2307.  
  2308.     return retval;
  2309. }
  2310.  
  2311. /*
  2312.  * Find the end of the tagaddress.
  2313.  * Return OK if ";\"\t" is following, FAIL otherwise.
  2314.  */
  2315.     static int
  2316. find_extra(pp)
  2317.     char_u    **pp;
  2318. {
  2319.     char_u    *str = *pp;
  2320.  
  2321.     /* Repeat for addresses separated with ';' */
  2322.     for (;;)
  2323.     {
  2324.     if (isdigit(*str))
  2325.         str = skipdigits(str);
  2326.     else if (*str == '/' || *str == '?')
  2327.     {
  2328.         str = skip_regexp(str + 1, *str, FALSE);
  2329.         if (*str != **pp)
  2330.         str = NULL;
  2331.         else
  2332.         ++str;
  2333.     }
  2334.     else
  2335.         str = NULL;
  2336.     if (str == NULL || *str != ';'
  2337.               || !(isdigit(str[1]) || str[1] == '/' || str[1] == '?'))
  2338.         break;
  2339.     ++str;    /* skip ';' */
  2340.     }
  2341.  
  2342.     if (str != NULL && STRNCMP(str, ";\"\t", 3) == 0)
  2343.     {
  2344.     *pp = str;
  2345.     return OK;
  2346.     }
  2347.     return FAIL;
  2348. }
  2349.